package com.xxl.job.executor.service.jobhandler;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.lang.Tuple;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.godtree.util.WranMsgUtils;
import com.godtree.util.bazhuayu.TaskTools;
import com.google.common.collect.Lists;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.executor.core.helper.TaskComplete;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.springframework.stereotype.Component;

/**
 * @author lisicheng
 * @date 2023-06-14
 */
@Component
public class BazhuayuApiTaskJob {

  @XxlJob("bazhuayuApiTaskJob")
  public void bazhuayuApiTaskJob() throws InterruptedException {

    // 获取任务参数
    // 任务参数为jsonArray格式 例如：["taskId1","taskId2",["taskId3","taskId4"]]
    String jobParam = XxlJobHelper.getJobParam();

    if (StrUtil.isBlank(jobParam)) {
      XxlJobHelper.handleFail("任务参数为空");
      return;
    }

    XxlJobHelper.log("任务参数为：{}", jobParam);

    // 判断任务参数是否为jsonArray格式
    if (!jobParam.startsWith(StrUtil.BRACKET_START) || !jobParam.endsWith(StrUtil.BRACKET_END)) {
      XxlJobHelper.handleFail("任务参数格式错误");
      return;
    }

    // 将任务参数转换为jsonArray
    JSONArray jsonArray = JSONUtil.parseArray(jobParam);

    if (jsonArray.isEmpty()) {
      XxlJobHelper.handleFail("任务参数为空");
      return;
    }

    // 创建线程池
    @SuppressWarnings("AlibabaThreadPoolCreation")
    ExecutorService executorService = Executors.newWorkStealingPool(jsonArray.size());
    CountDownLatch countDownLatch = new CountDownLatch(jsonArray.size());
    List<String> errorMsgList = Lists.newArrayList();

    // 遍历jsonArray
    // jsonArray中的每个元素都应该为字符串或者为jsonArray
    for (Object o : jsonArray) {

      executorService.execute(() -> {

        try {

          // 判断是否为字符串或者为jsonArray
          if (o instanceof String) {
            // 如果是字符串，直接调用八爪鱼api
            runTask((String) o);
          } else if (o instanceof JSONArray) {
            // 如果是jsonArray，遍历jsonArray，调用八爪鱼api
            JSONArray jsonArray1 = (JSONArray) o;
            for (Object o1 : jsonArray1) {
              // 如果是字符串，直接调用八爪鱼api
              if (o1 instanceof String) {
                runTask((String) o1);
              } else {
                XxlJobHelper.handleFail("任务参数格式错误");
              }
            }
          } else {
            XxlJobHelper.handleFail("任务参数格式错误");
          }

        } catch (Exception e) {
          String errorMsg = StrUtil.format("任务【{}】执行失败，失败原因：{}", JSONUtil.toJsonStr(o),
              ExceptionUtil.stacktraceToString(e));
          XxlJobHelper.log(errorMsg);
          errorMsgList.add(errorMsg);
        } finally {
          countDownLatch.countDown();
        }

      });

    }

    countDownLatch.await();
    executorService.shutdown();

    if (!errorMsgList.isEmpty()) {
      XxlJobHelper.handleFail(StrUtil.join(StrUtil.LF, errorMsgList));
      WranMsgUtils.send("[通过八爪鱼api执行任务]", StrUtil.join(StrUtil.LF, errorMsgList));
      return;
    }

    XxlJobHelper.handleSuccess("任务执行成功");

  }

  private static void runTask(String taskId) {
    XxlJobHelper.log("调用八爪鱼api：{}", taskId);

    Integer taskStatus = TaskTools.getTaskStatus(Lists.newArrayList(taskId)).get(taskId);
    if (ObjectUtil.equal(taskStatus, 0)) {
      XxlJobHelper.log("任务【{}】已经启动，无需重复启动", taskId);
      return;
    }

    // 调用八爪鱼api，启动任务
    Tuple startTask = TaskTools.startTask(taskId);
    boolean success = startTask.get(0);
    if (!success) {
      String errogMsg = StrUtil.format("任务【{}】启动失败，失败原因：{}", taskId, startTask.get(1));
      XxlJobHelper.log(errogMsg);
      throw new ArithmeticException(errogMsg);
    }

    XxlJobHelper.log("任务【{}】启动成功，描述：【{}】。等待一段时间后轮询任务状态", taskId,
        startTask.get(1));

    // 任务启动成功，等待5s
    ThreadUtil.sleep(TimeUnit.SECONDS.toMillis(5));

    XxlJobHelper.log("开始轮询任务状态");

    // 任务启动成功，轮询任务状态
    TaskComplete.of(taskId).execute();
  }

}
